//
// Created by Administrator on 2023-11-29.
//

#include "headers/framelesswindow.h"
#include <QMouseEvent>
#include <QDateTime>
#include <QFontDatabase>

FramelessWindow::FramelessWindow(QWidget *parent) :
        QWidget(parent), m_titlebar(Q_NULLPTR), m_borderWidth(2), m_bResizeable(true), minWindowWidth(300),
        minWindowHeight(80), currentTimeStamp(QDateTime::currentDateTime().currentMSecsSinceEpoch()) {
    setWindowFlag(Qt::FramelessWindowHint);
    setAttribute(Qt::WA_StyledBackground);
    setMouseTracking(true);
    qApp->installEventFilter(this);
}

void FramelessWindow::setResizeable(bool resizeable) {
    m_bResizeable = resizeable;
}

void FramelessWindow::setResizeableAreaWidth(int width) {
    if (0 > width) width = 0;
    m_borderWidth = width;
}

void FramelessWindow::setTitleBar(QWidget *titlebar) {
    m_titlebar = titlebar;
    if (!titlebar) return;
    connect(titlebar, SIGNAL(destroyed(QObject * )), this, SLOT(onTitleBarDestroyed()));
}

void FramelessWindow::onTitleBarDestroyed() {
    if (m_titlebar == QObject::sender()) {
        m_titlebar = Q_NULLPTR;
    }
}

void FramelessWindow::setCursorStyle(const QPoint &pos) {
    Qt::WindowFrameSection frameSection = getEdgeSection(pos);
    if (frameSection == Qt::NoSection) {
        setCursor(Qt::ArrowCursor);
    } else if (frameSection == Qt::LeftSection || frameSection == Qt::RightSection) {
        setCursor(Qt::SizeHorCursor);
    } else if (frameSection == Qt::TopSection || frameSection == Qt::BottomSection) {
        setCursor(Qt::SizeVerCursor);
    } else if (frameSection == Qt::TopLeftSection || frameSection == Qt::BottomRightSection) {
        setCursor(Qt::SizeFDiagCursor);
    } else if (frameSection == Qt::TopRightSection || frameSection == Qt::BottomLeftSection) {
        setCursor(Qt::SizeBDiagCursor);
    }
}

Qt::WindowFrameSection FramelessWindow::getEdgeSection(const QPoint &pos) {
    QList<Qt::WindowFrameSection> sections = {Qt::NoSection, Qt::LeftSection, Qt::RightSection, Qt::TopSection,
                                              Qt::BottomSection,
                                              Qt::TopLeftSection, Qt::TopRightSection, Qt::BottomLeftSection,
                                              Qt::BottomRightSection};
    for (Qt::WindowFrameSection section : sections) {
        if (isInFrameSection(pos, section)) {
            return section;
        }
    }
    return Qt::NoSection;
}

bool FramelessWindow::isInFrameSection(const QPoint &pos, Qt::WindowFrameSection edge) {
    QRect area = QRect(0, 0, width(), height()).adjusted(m_borderWidth, m_borderWidth, -m_borderWidth, -m_borderWidth);
    if (edge == Qt::NoSection) { // center包含于edge包含于corner，判断顺序必须是 center>edge>corner
        return area.contains(pos);
    }
    if (edge == Qt::LeftSection || edge == Qt::TopLeftSection || edge == Qt::BottomLeftSection) {
        area.adjust(-m_borderWidth * 2, 0, 0, 0); // 乘2是为了增加偏移量，超出窗体边缘，避免光标抖动
    }
    if (edge == Qt::RightSection || edge == Qt::TopRightSection || edge == Qt::BottomRightSection) {
        area.adjust(0, 0, m_borderWidth * 2, 0);
    }
    if (edge == Qt::TopSection || edge == Qt::TopLeftSection || edge == Qt::TopRightSection) {
        area.adjust(0, -m_borderWidth * 2, 0, 0);
    }
    if (edge == Qt::BottomSection || edge == Qt::BottomLeftSection || edge == Qt::BottomRightSection) {
        area.adjust(0, 0, 0, m_borderWidth * 2);
    }
    return area.contains(pos);
}

bool FramelessWindow::eventFilter(QObject *watched, QEvent *event) {
    if (event->type() == QEvent::MouseButtonPress) {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
        if (mouseEvent->button() == Qt::LeftButton) {
            // 如果鼠标按下位置位于窗口边缘，记录鼠标按下位置和窗口当前大小
            if (watched == this && !isInFrameSection(mouseEvent->pos(), Qt::NoSection)) {
//                qDebug() << "鼠标按下位置位于窗口边缘....";
                dragStartPosition = mouseEvent->globalPosition().toPoint();
                windowGeometry = geometry();
                frameSection = getEdgeSection(mouseEvent->pos());
                isResizing = true;
                return true; // 截取并处理该事件
                // 如果鼠标按下位置位于 m_titlebar 区域，记录鼠标按下位置
            } else if (m_titlebar != Q_NULLPTR && m_titlebar->isVisible() &&
                       m_titlebar->geometry().contains(mouseEvent->pos()) &&
                       isInFrameSection(mouseEvent->pos(), Qt::NoSection)) {
                ////                qDebug() << "鼠标按下位于 m_titlebar 区域....";
                dragStartPosition = mouseEvent->globalPosition().toPoint() - frameGeometry().topLeft();
                isDragging = true;
                return true; // 截取并处理该事件
            }

        }
    } else if (event->type() == QEvent::MouseMove) {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
        if (watched->isWindowType()) {
            setCursorStyle(mouseEvent->pos());
        }
        if (mouseEvent->buttons() & Qt::LeftButton) {
            // 如果正在缩放窗口，计算新的窗口大小并移动
            if (isResizeable() && watched->isWindowType() && isResizing) {
//                qDebug() << "正在缩放窗口....";
                QPoint delta = mouseEvent->globalPosition().toPoint() - dragStartPosition;
                if (frameSection == Qt::LeftSection) {
                    move(windowGeometry.topLeft() + QPoint(delta.x(), 0));
                    resize(windowGeometry.size() + QSize(-delta.x(), 0));
                } else if (frameSection == Qt::RightSection) {
                    resize(windowGeometry.size() + QSize(delta.x(), 0));
                } else if (frameSection == Qt::TopSection) {
                    resize(windowGeometry.size() + QSize(0, -delta.y()));
                    move(windowGeometry.topLeft() + QPoint(0, delta.y()));
                } else if (frameSection == Qt::BottomSection) {
                    resize(windowGeometry.size() + QSize(0, delta.y()));
                } else if (frameSection == Qt::TopLeftSection) {
                    resize(windowGeometry.size() + QSize(-delta.x(), -delta.y()));
                    move(windowGeometry.topLeft() + QPoint(delta.x(), delta.y()));
                } else if (frameSection == Qt::BottomRightSection) {
                    resize(windowGeometry.size() + QSize(delta.x(), delta.y()));
                } else if (frameSection == Qt::BottomLeftSection) {
                    resize(windowGeometry.size() + QSize(-delta.x(), delta.y()));
                    move(windowGeometry.topLeft() + QPoint(delta.x(), 0));
                } else if (frameSection == Qt::TopRightSection) {
                    resize(windowGeometry.size() + QSize(delta.x(), -delta.y()));
                    move(windowGeometry.topLeft() + QPoint(0, delta.y()));
                }
//                qDebug() << "width" << this->size().width();
//                qDebug() << "height" << this->size().height();
//                if (this->size().width() <= minWindowWidth) {
//                    this->resize(minWindowWidth, this->size().height());
//                }
//                if (this->size().height() <= minWindowHeight) {
//                    this->resize(this->size().width(), minWindowHeight);
//                }
                return true; // 截取并处理该事件
            } else if (isDragging) {
//                qDebug() << "正在拖动 spacer 区域....";
                // 如果正在拖动 spacer 区域，移动窗口
                QPoint newPos = mouseEvent->globalPosition().toPoint() - dragStartPosition;
                move(newPos);
                return true; // 截取并处理该事件
            }
        }
    } else if (event->type() == QEvent::MouseButtonRelease) {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
        isDragging = false;
        isResizing = false;
        if (m_titlebar != Q_NULLPTR && m_titlebar->isVisible() &&
            m_titlebar->geometry().contains(mouseEvent->pos()) &&
            isInFrameSection(mouseEvent->pos(), Qt::NoSection)) {

            long long tmpTimeStamp = QDateTime::currentDateTime().currentMSecsSinceEpoch();
            bool dbClick = isHeadDBClick(tmpTimeStamp);
            currentTimeStamp = tmpTimeStamp;
            if (dbClick) {
//                    qDebug() << "双击了";
                headDBClick();
            }
        }
    }
    return QWidget::eventFilter(watched, event); // 其他事件交给父类处理
}

bool FramelessWindow::isHeadDBClick(long long timestamp) {
    qDebug() << "==" << timestamp - currentTimeStamp;
    if (timestamp - currentTimeStamp >= 300) {
        return false;
    }
    return true;
}

void FramelessWindow::headDBClick() {
    if (isMaximized()) {
        showNormal();
    } else {
        showMaximized();
    }
}

void FramelessWindow::setMinWindowWidth(int width) {
    minWindowWidth = width;
}

void FramelessWindow::setMinWindowHeight(int height) {
    minWindowHeight = height;
}

void FramelessWindow::loadFonts(QList<QString> *fontFilePath) {
    for (int i = 0; i < fontFilePath->size(); i++) {
        QFontDatabase::addApplicationFont(fontFilePath->at(i));
    }
}

void FramelessWindow::loadStyleSheet(QList<QString> *styleFilePath) {
    QString css;
    for (int i = 0; i < styleFilePath->size(); i++) {
        QFile cssFile(styleFilePath->at(i));
        if (cssFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
            css.append(cssFile.readAll().data());
            cssFile.close();
        }
    }
    qApp->setStyleSheet(css);
}